package cn.yunyichina.provider.drug.service.impl;

import cn.yunyichina.provider.drug.dao.MatchedDao;
import cn.yunyichina.provider.drug.dao.MatchedListDao;
import cn.yunyichina.provider.drug.entity.Matched;
import cn.yunyichina.provider.drug.entity.MatchedList;
import cn.yunyichina.provider.drug.utils.ListUtils;
import cn.yunyichina.provider.drug.vo.OrderList;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.framework.page.PageInfo;
import cn.yunyichina.provider.framework.utils.UUIDUtil;
import cn.yunyichina.provider.iface.entity.base.OrderListVo;
import cn.yunyichina.provider.iface.entity.base.Org;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Administrator on 2017/7/27.
 */
@Service
public class MatchedServiceImpl {

    private Logger logger = LoggerFactory.getLogger(MatchedServiceImpl.class);

    @Autowired
    private MatchedDao matchedDao;

    @Autowired
    private MatchedListDao matchedListDao;

    /**
     * 根据条件查询药品匹配结果信息
     * @param data
     * @interface yyt.drug.matched.list
     * @return
     */
    public Response listMatched(String data, String sessionId) {
        logger.info("【drug模块-根据条件查询药品匹配结果】开始, 请求="+data,",sessionId=" + sessionId);

        Response response = new Response();

        Matched matchedRequest = null;
        List<Matched> matchedRespon = null;

        matchedRequest = JsonUtils.parseObject(data, Matched.class);

        //检查入参
        if(StringUtils.isBlank(matchedRequest.getOrderNo())){
            response.setResultCodeAndMessage("23001", "order_no不能为空");
            logger.info("【drug模块-匹配任务】,order_no不能为空");
            return response;
        }

        try {
            List<String> orderColumns = new ArrayList<String>();
            PageInfo pageInfo = null;
            if(matchedRequest != null){
                orderColumns.add("PAY_AMOUNT");
                pageInfo = JsonUtils.parseObject(data, PageInfo.class);
                if(pageInfo != null){
                    matchedRespon  = matchedDao.select(matchedRequest, orderColumns , false ,pageInfo);
                }else{
                    matchedRespon  = matchedDao.select(matchedRequest, orderColumns , false);
                }
            }

            if(matchedRespon != null && matchedRespon.size() > 0){
                if(StringUtils.isNotBlank(matchedRespon.get(0).getCompanyId())){
                    logger.info("【drug模块-匹配任务】,【匹配表drug_matched已有数据】,【企业ID不为空】->匹配成功");

                    List<Matched> resultList = new ArrayList<>();
                    for (Matched matched : matchedRespon) {
                        // 查询组织信息-----------------------------------------------start
                        Map<String, String> paramMap = new HashMap<String, String>();
                        paramMap.put("parent_id", matched.getCompanyId());
                        logger.info("【drug模块-匹配任务-查询组织信息】, yyt.base.org.list request=" + JSON.toJSONString(paramMap));
                        Response orgResponse = BaseService.callUnderlineFromInternal("yyt.base.org.list", JSON.toJSONString(paramMap));
                        logger.info("【drug模块-匹配任务-查询组织信息】, yyt.base.org.list response=" + JSONObject.toJSONString(orgResponse));
                        if (!"1000".equals(orgResponse.getResultCode())) {
                            response.setResultCodeAndMessage("234011", "查询门店信息失败:" + orgResponse.getResultMessage() + "！");
                            return response;
                        }
                        Map<String,Object> maps = JsonUtils.parseObject(orgResponse.getResult(), Map.class);
                        List<Org> orgList = JsonUtils.parseObject(maps.get("list"), List.class);
                        matched.setStores(orgList);
                        resultList.add(matched);
                        // 查询组织信息-----------------------------------------------end
                    }

                    response.setResult(JsonUtils.toJsonString(resultList));
                    response.setResultCodeAndMessage("0", "查询成功，有匹配药店");
                    return response;
                }else{
                    logger.info("【drug模块-匹配任务】,【匹配表drug_matched已有数据】,【企业ID为空】->匹配失败");
                    response.setResult(JsonUtils.toJsonString(matchedRespon));
                    response.setResultCodeAndMessage("23009", "无匹配药店");
                    return response;
                }
            }else{
                logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】->开始检查drug_matched_list");
                response.setResultCodeAndMessage("23002" , "药品正在匹配中，匹配结果请稍后查询");

                MatchedList matchedListQuery = new MatchedList();
                matchedListQuery.setOrderNo(matchedRequest.getOrderNo());
                List<MatchedList> MatchedListQueryResult = matchedListDao.select(matchedListQuery);

                if(MatchedListQueryResult != null && MatchedListQueryResult.size() > 0){
                    logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】,【匹配表drug_matched_list有数据】->上一次匹配任务仍在进行中，本次任务中断执行");
                    response.setResultCodeAndMessage("23002" , "药品正在匹配中，匹配结果请稍后查询");
                    return response;
                }else{
                    logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】,【匹配表drug_matched_list无数据】->开始检查数据条数");

                    int count = 0;
                    Map<String, String> orderDataMap = new HashMap<String, String>();
                    orderDataMap.put("order_no", matchedRequest.getOrderNo());
                    logger.info("【drug模块-查询订单明细信息】, yyt.base.order.item.list request=" + JSON.toJSONString(orderDataMap));
                    Response ordResponse = BaseService.callUnderlineFromInternal("yyt.base.order.item.list",
                            JsonUtils.toJsonString(orderDataMap));
                    logger.info("【drug模块-查询订单明细信息】, yyt.base.order.item.list response=" + JSONObject.toJSONString(ordResponse));
                    if (!"0".equals(ordResponse.getResultCode())) {
                        throw new CallException("14010","not found order by order_no=" + matchedRequest.getOrderNo());
                    }
                    List<OrderListVo> orderListVoList = JsonUtils.parseObject(ordResponse.getResult(), List.class);
                    count = orderListVoList.size();
                    if(count <= 0){
                        logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】,【匹配表drug_matched_list无数据】,【处方明细条数=0】->匹配失败");

                        Matched matchedResult = new Matched();
                        matchedResult.setId(UUIDUtil.get32UUID());
                        matchedResult.setMatchedNo(matchedRequest.getOrderNo());
                        matchedResult.setOrderNo(matchedRequest.getOrderNo());
                        matchedResult.setMatchedStatus((short) 2);
                        matchedResult.setExceptionReason("匹配失败：处方明细条数=0");
                        matchedResult.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        matchedDao.insert(matchedResult);
                        response.setResultCodeAndMessage("23009", "无匹配药店");
                        return response;
                    }

                    List<MatchedList> matchedListResult = matchedListDao.createMatchedList(matchedRequest.getOrderNo(), count);

                    if(matchedListResult != null && matchedListResult.size() >0){
                        logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】,【匹配表drug_matched_list无数据】,【匹配到药品条数等于处方明细条数】->匹配成功");

                        String type = "1";
                        matchedListResult = chooseDrugByRule(matchedListResult, type);

                        for (MatchedList matchedList : matchedListResult) {
                            matchedList.setId(UUIDUtil.get32UUID());
                            if(matchedList.getChooseFlag() == null){
                                matchedList.setChooseFlag((short)0);
                            }
                        }
                        matchedListDao.batchInsert(matchedListResult);

                        List<Matched> matchedResult = matchedDao.createMatched(matchedRequest.getOrderNo());
                        for (Matched matched : matchedResult) {
                            matched.setId(UUIDUtil.get32UUID());
                            matched.setMatchedStatus((short) 1);
                            matched.setExceptionReason("匹配成功");
                            matched.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        }

                        matchedDao.batchInsert(matchedResult);

                        List<Matched> resultList = new ArrayList<>();

                        for (Matched matched : matchedResult) {
                            // 查询组织信息-----------------------------------------------start
                            Map<String, String> paramMap = new HashMap<String, String>();
                            paramMap.put("parent_id", matched.getCompanyId());
                            logger.info("【drug模块-匹配任务-查询组织信息】, yyt.base.org.list request=" + JSON.toJSONString(paramMap));
                            Response orgResponse = BaseService.callUnderlineFromInternal("yyt.base.org.list", JSON.toJSONString(paramMap));
                            logger.info("【drug模块-匹配任务-查询组织信息】, yyt.base.org.list response=" + JSONObject.toJSONString(orgResponse));
                            if (!"1000".equals(orgResponse.getResultCode())) {
                                response.setResultCodeAndMessage("234011", "查询门店信息失败:" + orgResponse.getResultMessage() + "！");
                                return response;
                            }
                            Map<String,Object> maps = JsonUtils.parseObject(orgResponse.getResult(), Map.class);
                            List<Org> orgList = JsonUtils.parseObject(maps.get("list"), List.class);
                            matched.setStores(orgList);
                            resultList.add(matched);
                            // 查询组织信息-----------------------------------------------end
                        }

                        response.setResult(JsonUtils.toJsonString(resultList));
                        response.setResultCodeAndMessage("0", "查询成功，有匹配药店");
                        return response;
                    }else{
                        logger.info("【drug模块-匹配任务】,【匹配表drug_matched无数据】,【匹配表drug_matched_list无数据】,【匹配不到药品】->匹配失败");

                        Matched matchedResult = new Matched();
                        matchedResult.setId(UUIDUtil.get32UUID());
                        matchedResult.setMatchedNo(matchedRequest.getOrderNo());
                        matchedResult.setOrderNo(matchedRequest.getOrderNo());
                        matchedResult.setMatchedStatus((short) 2);
                        matchedResult.setExceptionReason("匹配失败：无对应的药品");
                        matchedResult.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                        matchedDao.insert(matchedResult);
                        response.setResultCodeAndMessage("23009", "无匹配药店");
                    }
                }
            }
        } catch (CallException e) {
            e.printStackTrace();
            response.setResultCodeAndMessage("23999", e.getMessage());
        }finally {
            logger.info("【drug模块-根据条件查询药品匹配结果】结束, 返回结果=" + JsonUtils.toJsonString(response));
        }

        return response;
    }

    /**
     * 获取成功匹配之外的药店列表
     * @param data
     * @interface yyt.drug.matched.other.hospital.list
     * @return
     */
    public Response listMatchedOtherHospital(String data, String sessionId){
        logger.info("【drug模块-获取成功匹配之外的药店列表】开始, 请求="+data,",sessionId=" + sessionId);
        Response response = new Response();

        try {
            Map<String,String> vo = JsonUtils.parseObject(data, Map.class);
            String orderNo = vo.get("order_no");

            if(StringUtils.isBlank(orderNo)){
                response.setResultCodeAndMessage("23001", "order_no不能为空");
                logger.info("【drug模块-获取成功匹配之外的药店列表】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            Map<String, String> paramMap = new HashMap<String, String>();
            paramMap.put("org_type", "7");
            paramMap.put("sup_outside_interface", "2");
            logger.info("【drug模块-获取成功匹配之外的药店列表-查询药店】, yyt.base.org.list request=" + JSON.toJSONString(paramMap));
            Response orgResponse = BaseService.callUnderlineFromInternal("yyt.base.org.list", JSON.toJSONString(paramMap));
            logger.info("【drug模块-获取成功匹配之外的药店列表-查询药店】, yyt.base.org.list response=" + JSONObject.toJSONString(orgResponse));
            if (!"1000".equals(orgResponse.getResultCode())) {
                response.setResultCodeAndMessage("23001", "查询药店失败:" + orgResponse.getResultMessage() + "！");
                return response;
            }
            List<Org> orgList = JsonUtils.parseArray(JsonUtils.toJsonString(JsonUtils.parseObject(orgResponse.getResult()).get("list")), Org.class);


            Matched matchedQuery = new Matched();
            matchedQuery.setOrderNo(orderNo);
            List<Matched> MatchedQueryResult = matchedDao.select(matchedQuery);
            logger.info("【drug模块-获取成功匹配之外的药店列表-查询匹配结果】返回匹配结果=" + JsonUtils.toJsonString(MatchedQueryResult));

            List<Org> orgResultList = new ArrayList<>();

            if(MatchedQueryResult == null || MatchedQueryResult.size() == 0 || (MatchedQueryResult.size() > 0 && StringUtils.isBlank(MatchedQueryResult.get(0).getCompanyCode()))){
                orgResultList = orgList;
            }else{
                List<String> matchedList = new ArrayList<>();
                for (Matched matched : MatchedQueryResult) {
                    matchedList.add(matched.getCompanyCode());
                }

                for (Org org : orgList) {
                    if(matchedList.contains(org.getOrgCode())){
                        continue;
                    }else{
                        orgResultList.add(org);
                    }
                }
            }

            for (Org org : orgResultList) {
                // 查询子组织信息-----------------------------------------------start
                paramMap = new HashMap<String, String>();
                paramMap.put("parent_id", org.getId());
                logger.info("【drug模块-获取成功匹配之外的药店列表-查询组织信息】, yyt.base.org.list request=" + JSON.toJSONString(paramMap));
                orgResponse = BaseService.callUnderlineFromInternal("yyt.base.org.list", JSON.toJSONString(paramMap));
                logger.info("【drug模块-获取成功匹配之外的药店列表-查询组织信息】, yyt.base.org.list response=" + JSONObject.toJSONString(orgResponse));
                if (!"1000".equals(orgResponse.getResultCode())) {
                    response.setResultCodeAndMessage("23011", "查询门店信息失败:" + orgResponse.getResultMessage() + "！");
                    return response;
                }
                Map<String,Object> maps = JsonUtils.parseObject(orgResponse.getResult(), Map.class);
                orgList = JsonUtils.parseObject(maps.get("list"), List.class);
                org.setSubOrgList(orgList);
            }

            response.setResultCodeAndMessageAndResult("0", "查询成功", JsonUtils.toJsonString(orgResultList));
            logger.info("【drug模块-获取成功匹配之外的药店列表】结束, 返回结果=" + JsonUtils.toJsonString(orgResultList));
            return response;

        } catch (Exception e) {
            e.printStackTrace();
            response.setResultCodeAndMessage("23999", "系统异常:" + e.getMessage());
        }

        logger.info("【drug模块-获取成功匹配之外的药店列表】结束, 返回结果=" + JsonUtils.toJsonString(response));
        return response;
    }

    /**
     * 根据指定规则选择药品并返回选择结果
     * @param list 匹配结果
     * @param type 规则类型
     * @return
     */
    private List<MatchedList> chooseDrugByRule(List<MatchedList> list, String type){
        logger.info("【drug模块-根据指定规则选择药品并返回选择结果】开始, 请求list=" + JsonUtils.toJsonString(list) + ",type=" + type);

        List<MatchedList> returnList = new ArrayList<>();

        if("1".equals(type)){
            Map<String, List<MatchedList>> mapCompanyCode = new HashMap<String, List<MatchedList>>();
            try {
                ListUtils.listGroup2Map(list, mapCompanyCode, MatchedList.class, "getCompanyCode");
                for(Map.Entry<String, List<MatchedList>> entryCompanyCode : mapCompanyCode.entrySet()){
                    List<MatchedList> listCompany = entryCompanyCode.getValue();

                    Map<String, List<MatchedList>> mapGoodsId = new HashMap<String, List<MatchedList>>();
                    ListUtils.listGroup2Map(listCompany, mapGoodsId, MatchedList.class, "getGoodsId");
                    for(Map.Entry<String, List<MatchedList>> entryGoodsId : mapGoodsId.entrySet()){
                        List<MatchedList> listGoodsId = entryGoodsId.getValue();
                        ListUtils.Sort(listGoodsId, "getPrice", "Double", "asc");
                        listGoodsId.get(0).setChooseFlag((short)1);
                        returnList.addAll(listGoodsId);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            returnList = null;
        }

        logger.info("【drug模块-根据指定规则选择药品并返回选择结果】结束, 返回结果=" + JsonUtils.toJsonString(returnList));
        return returnList;
    }

    /**
     * 选中匹配结果药品接口
     * @param data
     * @interface yyt.drug.matched.details.choose
     * @return
     */
    public Response chooseMatchedDetails(String data, String sessionId){
        logger.info("【drug模块-选中匹配结果药品接口】开始, 请求="+data,",sessionId=" + sessionId);
        Response response = new Response();

        try {
            Map<String,String> vo = JsonUtils.parseObject(data,Map.class);
            String orderNo = vo.get("order_no");
            String companyCode = vo.get("company_code");
            String chooseItems = vo.get("choose_items");

            if(StringUtils.isBlank(orderNo)){
                response.setResultCodeAndMessage("23001", "order_no不能为空");
                logger.info("【drug模块-选中匹配结果药品接口】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            if(StringUtils.isBlank(companyCode)){
                response.setResultCodeAndMessage("23001", "company_code不能为空");
                logger.info("【drug模块-选中匹配结果药品接口】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            if(StringUtils.isBlank(chooseItems)){
                response.setResultCodeAndMessage("23001", "choose_items不能为空");
                logger.info("【drug模块-选中匹配结果药品接口】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            Matched matchedQuery = new Matched();
            matchedQuery.setOrderNo(orderNo);
            matchedQuery.setCompanyCode(companyCode);
            List<Matched> matchedList =  matchedDao.select(matchedQuery);
            if(org.springframework.util.CollectionUtils.isEmpty(matchedList)){
                response.setResultCodeAndMessage("23003", "查询不到该药店的匹配结果");
                logger.info("【drug模块-选中匹配结果药品接口】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }
            Matched matched = matchedList.get(0);

            String[] ids = chooseItems.split(";");
            List<String> list = Arrays.asList(ids);
            matchedListDao.unChooseByIds(orderNo, companyCode, list);
            matchedListDao.toChooseByIds(orderNo, companyCode, list);

            matchedDao.updatePayAmount(orderNo, companyCode, matched.getId());

            Matched newMatched = matchedDao.selectById(matched.getId());
            Map<String,Object> map = new HashMap<>();
            map.put("pay_amount", newMatched.getPayAmount());

            response.setResultCodeAndMessageAndResult("0", "更新成功", JsonUtils.toJsonString(map));
        } catch (Exception e) {
            e.printStackTrace();
            response.setResultCodeAndMessage("23999", "系统异常:" + e.getMessage());
        }

        logger.info("【drug模块-替换选择药品匹配结果明细信息】结束, 返回结果=" + JsonUtils.toJsonString(response));
        return response;
    }

    /**
     * 根据条件查询药品匹配结果明细信息
     * @param data
     * @interface yyt.drug.matched.details.list
     * @return
     */
    public Response listMatchedDetails(String data, String sessionId){
        logger.info("【drug模块-根据条件查询药品匹配明细结果】开始, 请求="+data,",sessionId=" + sessionId);
        Response response = new Response();

        try {
            Map<String,String> vo = JsonUtils.parseObject(data,Map.class);
            String orderNo = vo.get("order_no");
            String companyCode = vo.get("company_code");

            if(StringUtils.isBlank(orderNo)){
                response.setResultCodeAndMessage("23001", "order_no不能为空");
                logger.info("【drug模块-根据条件查询药品匹配明细结果】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            if(StringUtils.isBlank(companyCode)){
                response.setResultCodeAndMessage("23001", "company_code不能为空");
                logger.info("【drug模块-根据条件查询药品匹配明细结果】结束, 返回结果=" + JsonUtils.toJsonString(response));
                return response;
            }

            Map<String, String> orderDataMap = new HashMap<String, String>();
            orderDataMap.put("order_no", orderNo);
            logger.info("【drug模块-查询订单明细信息】, yyt.base.order.item.list request=" + JSON.toJSONString(orderDataMap));
            Response ordResponse = BaseService.callUnderlineFromInternal("yyt.base.order.item.list",
                    JsonUtils.toJsonString(orderDataMap));
            logger.info("【drug模块-查询订单明细信息】, yyt.base.order.item.list response=" + JSONObject.toJSONString(ordResponse));
            if (!"0".equals(ordResponse.getResultCode())) {
                throw new CallException("23009","【drug模块-根据条件查询药品匹配明细结果】查询不到order_no[" + orderNo + "]的订单明细");
            }
            List<OrderList> orderListList = JsonUtils.parseArray(ordResponse.getResult(), OrderList.class);

            for (OrderList orderList : orderListList) {
                MatchedList matchedList = new MatchedList();
                matchedList.setOrderNo(orderNo);
                matchedList.setCompanyCode(companyCode);
                matchedList.setGoodsId(orderList.getGoodsId());
                List<String> orderColumns = new ArrayList<String>();
                orderColumns.add("PRICE");
                List<MatchedList> matchedListList = matchedListDao.select(matchedList, orderColumns, true);
                if(matchedListList != null && matchedListList.size() > 0){
                    orderList.setMatchedListList(matchedListList);
                }else{
                    response.setResultCodeAndMessage("23009", "【drug模块-根据条件查询药品匹配明细结果】查询不到order_no[" + orderNo + "],goods_id[" + orderList.getGoodsId() + "]的匹配明细");
                    logger.info("【drug模块-根据条件查询药品匹配明细结果】结束, 返回结果=" + JsonUtils.toJsonString(response));
                    return response;
                }
            }

            response.setResult(JsonUtils.toJsonString(orderListList));
            response.setResultCodeAndMessage("0", "成功");

        } catch (Exception e) {
            e.printStackTrace();
            response.setResultCodeAndMessage("23999", "系统异常:" + e.getMessage());
        }

        logger.info("【drug模块-根据条件查询药品匹配明细结果】结束, 返回结果=" + JsonUtils.toJsonString(response));
        return response;
    }
}
